/*
 * IndexHeaderPage.cpp
 *
 *  Created on: 30-Oct-2013
 *      Author: sriram
 */

#include "IndexHeaderPage.h"
#include "../dependency/debug.h"
#include "BPlusTreeLeafNode.h"
#include "BPlusTreeNode.h"
#include "../BufferManager/BufferManager.h"
#include "../Global/StructureHeaders.h"
#include "../dependency/StatusCodes.h"
#include "../dependency/ExternDefOfGlobalVariables.h"
//#include "../dependency/GlobalConstants.h"

#include <math.h>

using namespace std;

IndexHeaderPage::IndexHeaderPage() {
	// TODO Auto-generated constructor stub
    colSizes_=NULL;
    colTypes_=NULL;
}

IndexHeaderPage::IndexHeaderPage(int indexHeaderPageNumber) {
	DEBUG_B("Opening Page number "<<indexHeaderPageNumber);
	BufferManager *buffMgr = BufferManager::getInstance();
	int err = buffMgr->getPage(indexHeaderPageNumber, pageData_);
        if(err!=SUCCESS) constructorErrorStatus= err;
	memcpy(&indexPageHeader_, pageData_, sizeof(indexPageHeader_));
	DEBUG_B("Root Page no: "<<indexPageHeader_.rootPageNumber);
	initializeColumnInformation();	// Inititalizing the column Information
	DEBUG("new page head in cons"<<indexPageHeader_.pgHeader.toString());
}

void IndexHeaderPage::initializeColumnInformation() {
	int offset = sizeof(IndexPageHeaderStructure);
	colTypes_ = new int[indexPageHeader_.noColumns];
	colSizes_ = new int[indexPageHeader_.noColumns];

	for(int i=0; i<indexPageHeader_.noColumns; i++, offset+=sizeof(int))
		memcpy(&colTypes_[i], &pageData_[offset], sizeof(int));

	for(int i=0; i<indexPageHeader_.noColumns; i++, offset+=sizeof(int))
		memcpy(&colSizes_[i], &pageData_[offset], sizeof(int));
}

STATUS_CODE IndexHeaderPage::createIndexHeaderPage(int noColumns,
		int colTypes[], int colSizes[], int keySize) {
	DEBUG_B("Before Buff Manager");
	BufferManager *buffMgr = BufferManager::getInstance();
	DEBUG_B("After Buff Manager");
	int newPageNumber;
	DEBUG_B("Before New Page");
	buffMgr->getNewPage(newPageNumber, pageData_);

	DEBUG_B("After New Page "<<newPageNumber);
	memcpy(&indexPageHeader_, pageData_, sizeof(indexPageHeader_));
	DEBUG("new page head in create index head page***"<<indexPageHeader_.pgHeader.toString());
	indexPageHeader_.noColumns = noColumns;
	indexPageHeader_.keySize = keySize;
	indexPageHeader_.pgHeader.pageType = TYPE_INDEX_HEADER_PAGE;
	indexPageHeader_.maxRecordsInLeaf = (int) floor((PAGE_SIZE - BPlusTreeLeafNode::getLeafNodeHeaderSize())/(keySize+6)); //RID_LEN
	indexPageHeader_.fanOut = floor((PAGE_SIZE-BPlusTreeNode::getBPlusGeneralNodeHeaderSize() - sizeof(int))/(keySize+4));
	indexPageHeader_.rootPageNumber = -1;
	indexPageHeader_.height = 0;
	indexPageHeader_.noKeys = 0;
	indexPageHeader_.noColumns = noColumns;
	memcpy(pageData_, &indexPageHeader_, sizeof(indexPageHeader_));

	int offset = sizeof(indexPageHeader_);
	for(int i=0; i<noColumns; i++, offset+=sizeof(int))
		memcpy(&pageData_[offset], &colTypes[i], sizeof(int));

	for(int i=0; i<noColumns; i++, offset+=sizeof(int))
		memcpy(&pageData_[offset], &colSizes[i], sizeof(int));

	DEBUG_B("Before Initialization");
	initializeColumnInformation();
	DEBUG_B("After Initialization");
	return SUCCESS;
}

STATUS_CODE IndexHeaderPage::createIndexHeaderPage(int noColumns, int fanout,
		int colTypes[], int colSizes[], int keySize) {
	DEBUG_B("Before Buff Manager");
	BufferManager *buffMgr = BufferManager::getInstance();
	DEBUG_B("After Buff Manager");
	int newPageNumber;
	DEBUG_B("Before New Page");
	buffMgr->getNewPage(newPageNumber, pageData_);

	DEBUG_B("After New Page "<<newPageNumber);
	memcpy(&indexPageHeader_, pageData_, sizeof(indexPageHeader_));
	DEBUG("new page head in create index head page***"<<indexPageHeader_.pgHeader.toString());
	indexPageHeader_.noColumns = noColumns;
	indexPageHeader_.keySize = keySize;
	indexPageHeader_.pgHeader.pageType = TYPE_INDEX_HEADER_PAGE;
	indexPageHeader_.maxRecordsInLeaf = fanout;//(int) floor((PAGE_SIZE - BPlusTreeLeafNode::getLeafNodeHeaderSize())/(keySize+6)); //RID_LEN
	indexPageHeader_.fanOut = fanout;//(int) floor((PAGE_SIZE-BPlusTreeNode::getBPlusGeneralNodeHeaderSize())/(keySize+4));
	indexPageHeader_.rootPageNumber = -1;
	indexPageHeader_.height = 0;
	indexPageHeader_.noKeys = 0;
	indexPageHeader_.noColumns = noColumns;
	memcpy(pageData_, &indexPageHeader_, sizeof(indexPageHeader_));

	int offset = sizeof(indexPageHeader_);
	for(int i=0; i<noColumns; i++, offset+=sizeof(int))
		memcpy(&pageData_[offset], &colTypes[i], sizeof(int));

	for(int i=0; i<noColumns; i++, offset+=sizeof(int))
		memcpy(&pageData_[offset], &colSizes[i], sizeof(int));

	DEBUG_B("Before Initialization");
	initializeColumnInformation();
	DEBUG_B("After Initialization");
	return SUCCESS;
}

IndexHeaderPage::~IndexHeaderPage() {
	// TODO Auto-generated destructor stub
	BufferManager *buffMgr = BufferManager::getInstance();
	buffMgr->releasePage(indexPageHeader_.pgHeader.pageNumber, true);
    if(colTypes_!=NULL)
        delete colTypes_;
    if(colSizes_!=NULL)
        delete colSizes_;
}

int IndexHeaderPage::getFanOut() {
	memcpy(&indexPageHeader_, pageData_, sizeof(indexPageHeader_));
	return indexPageHeader_.fanOut;
}

void IndexHeaderPage::setFanOut(int fanOut) {
	indexPageHeader_.fanOut = fanOut;
	memcpy(pageData_, &indexPageHeader_, sizeof(indexPageHeader_));
}

int IndexHeaderPage::getHeight() {
	memcpy(&indexPageHeader_, pageData_, sizeof(indexPageHeader_));
	return indexPageHeader_.height;
}

void IndexHeaderPage::setHeight(int height) {
	indexPageHeader_.height = height;
	memcpy(pageData_, &indexPageHeader_, sizeof(indexPageHeader_));
}

void IndexHeaderPage::setKeySize(int keySize) {
	indexPageHeader_.keySize = keySize;
	memcpy(pageData_, &indexPageHeader_, sizeof(indexPageHeader_));
}

int IndexHeaderPage::getMaxRecordsInLeaf() {
	memcpy(&indexPageHeader_, pageData_, sizeof(indexPageHeader_));
	return indexPageHeader_.maxRecordsInLeaf;
}

void IndexHeaderPage::setMaxRecordsInLeaf(int maxRecordsInLeaf) {
	indexPageHeader_.maxRecordsInLeaf = maxRecordsInLeaf;
	memcpy(pageData_, &indexPageHeader_, sizeof(indexPageHeader_));
}

int IndexHeaderPage::getNoColumns() {
	memcpy(&indexPageHeader_, pageData_, sizeof(indexPageHeader_));
	return indexPageHeader_.noColumns;
}

void IndexHeaderPage::setNoColumns(int noColumns) {
	indexPageHeader_.noColumns = noColumns;
	memcpy(pageData_, &indexPageHeader_, sizeof(indexPageHeader_));
}

int IndexHeaderPage::getNoKeys() {
	memcpy(&indexPageHeader_, pageData_, sizeof(indexPageHeader_));
	return indexPageHeader_.noKeys;
}

void IndexHeaderPage::setNoKeys(int noKeys) {
        indexPageHeader_.noKeys = noKeys;
        memcpy(pageData_, &indexPageHeader_, sizeof(indexPageHeader_));
}

int IndexHeaderPage::getRootPageNumber() {
	memcpy(&indexPageHeader_, pageData_, sizeof(indexPageHeader_));
	return indexPageHeader_.rootPageNumber;
}

void IndexHeaderPage::setRootPageNumber(int rootPageNumber) {
	indexPageHeader_.rootPageNumber = rootPageNumber;
	memcpy(pageData_, &indexPageHeader_, sizeof(indexPageHeader_));
}

string IndexHeaderPage::toString(){
	ostringstream strStream;
	strStream<<"**********************************************"<<endl;
	strStream<<"INDEX HEADER PAGE  NUMBER: "<<getPageNumber()<<endl;
	strStream<<"ROOT PAGE NUMBER: "<<getRootPageNumber()<<endl;
	strStream<<"FAN OUT: "<<getFanOut()<<endl;
	strStream<<"HEIGHT: "<<getHeight()<<endl;
	strStream<<"MAX RECORDS IN LEAF: "<<getMaxRecordsInLeaf()<<endl;
	strStream<<"KEYSIZE: "<<getKeySize()<<endl;
	strStream<<"NUMBER OF KEYS: "<<getNoKeys()<<endl;
	strStream<<"NUMBER OF COLS IN INDEX: "<<getNoColumns()<<endl;
	strStream<<"**********************************************"<<endl;

	return strStream.str();
}

int IndexHeaderPage::getKeySize() {
	memcpy(&indexPageHeader_, pageData_, sizeof(indexPageHeader_));
	return indexPageHeader_.keySize;
}

int IndexHeaderPage::getPageNumber() {
	memcpy(&indexPageHeader_, pageData_, sizeof(indexPageHeader_));
	return indexPageHeader_.pgHeader.pageNumber;
}

int* IndexHeaderPage::getColTypes(){
    return this->colTypes_;
}
int* IndexHeaderPage::getColSizes(){
    return this->colSizes_;
}